package com.gitee.wsl.doc.prosemirror.transform.ext

import com.gitee.wsl.doc.prosemirror.exception.RangeError
import com.gitee.wsl.doc.prosemirror.exception.TransformError
import com.gitee.wsl.doc.prosemirror.model.mark.Mark
import com.gitee.wsl.doc.prosemirror.model.mark.MarkType
import com.gitee.wsl.doc.prosemirror.transform.TransformAble
import com.gitee.wsl.doc.prosemirror.transform.step.AddNodeMarkStep
import com.gitee.wsl.doc.prosemirror.transform.step.AttrStep
import com.gitee.wsl.doc.prosemirror.transform.step.DocAttrStep
import com.gitee.wsl.doc.prosemirror.transform.step.RemoveNodeMarkStep
import com.gitee.wsl.doc.prosemirror.transform.step.Step
import com.gitee.wsl.doc.prosemirror.util.safeMode
import kotlin.apply

// Apply a new step in this transform, saving the result. Throws an error when the step fails.
fun<T: TransformAble> T.step(step: Step) = apply {
    val result = this.maybeStep(step)
    if (result.failed != null) {
        val exception = TransformError(result.failed)
        this.error = exception
        if (!safeMode) throw exception
    }
}

// Set a single attribute on a given node to a new value.
// The `pos` addresses the document content. Use `setDocAttribute`
// to set attributes on the document itself.
fun<T: TransformAble> T.setNodeAttribute(pos: Int, attr: String, value: Any) = this.apply {
    step(AttrStep(pos, attr, value))
}

// Set a single attribute on the document to a new value.
fun<T: TransformAble> T.setDocAttribute(attr: String, value: Any) = this.apply {
    step(DocAttrStep(attr, value))
}

